// node源码 多数都是构造函数
//1. 历史遗留问题
//2. 原型可以分开写 方便扩展


function EventEmitter(){
  this._events  = Object.create(null); //fn.prototype = null -> this._events = new fn
}
// 订阅 创建关系
EventEmitter.prototype.on = function (eventName, callback) { // {'吃饭':[]}
  /*
    因为使用的是构造函数，故是没法使用类的extends的
    ，也就是说如果有一个构造函数使用，util.inherits继承本构造函数，它new的实例是没有this._events属性的
    ，故这里需要检查

    > util.inherits 只会继承公有属性 原型上的属性
      即↓
      Object.setPrototypeOf(Child.prototype,Parent.prototype);
      ↕等价于
      Child.prototype.__proto__ = Parent.prototype;
  */
  if (!this._events) {
    this._events = Object.create(null);
  }
  if (eventName !== 'newListener') {
    if (this._events['newListener']) {
      this._events['newListener'].forEach(fn => fn(eventName))
    }
  }
  let arr = this._events[eventName] || (this._events[eventName] = []);
  arr.push(callback)
};
EventEmitter.prototype.once = function (eventName, callback) {
  const once = (...args) => { // 高阶函数
    callback(...args);// 先执行原有的逻辑
    this.off(eventName, once);// 在将这个函数移除掉
  };
  once.l = callback; //针对once注册的fn，参考02.js的情景 girl.off('一个once注册的事件', listener)
  this.on(eventName, once);
};
// 让对应的函数依次执行
EventEmitter.prototype.emit = function (eventName, ...args) {
  if (!this._events) {
    this._events = Object.create(null);
  }
  if (this._events[eventName]) {
    this._events[eventName].forEach(fn => fn(...args));
  }
};
EventEmitter.prototype.off = function (eventName, fn) {
  if (this._events[eventName]) {
    //  this._events[eventName] = [once]
    this._events[eventName] = this._events[eventName].filter(item => {
      return item !== fn && /* 针对once注册的fn，参考02.js的情景 girl.off('一个once注册的事件', listener)→ */item.l !== fn
    })
  }
};
module.exports = EventEmitter;


//emitter.listenerCount(eventName) //返回正在监听的名为 eventName 的事件的监听器的数量。
//emitter.listeners(eventName) //返回名为 eventName 的事件的监听器数组的副本。
